/**
 * 获取流程定义
 *
 * 输入参数:
 *    CardID:       卡片的ID, 用以按卡片查询最新版本的流程定义
 *    WorkflowID:   流程定义的ID
 *
 * 输出参数:
 *    流程定义的record记录。附加特殊值：{nodes, start, end, node}
 */
(() => {
  // 私有区域
  function noop() { }

  return function ({ UID, CardID, WorkflowID, record }) {
    // 验证输入参数
    if (!UID) throw Error("无效会话");

    // 1. 加载流程定义
    const { Rows: wfs } = A.job.CardR(UID, 'B.流程定义', null, {
      Filter: [CardID ? { and: [['数据卡片', '=', CardID], ['启用标记', '=', true]] } : null, WorkflowID ? ['ID', '=', WorkflowID] : null],
      Order: { '版本号': 'desc' },
    });
    if (wfs.length === 0) throw Error("未找到有效的流程定义");
    const wf_matchs = [];
    if (CardID) {
      // 按名称分组, 取最新版本
      const names = new Map();
      wfs.forEach(wf => {
        if (names.has(wf.名称)) return;
        names.set(wf.名称, wf);
      });
      // 唯一匹配流程定义
      names.forEach(wf => {
        const onMatch = wf.匹配条件脚本 ? eval('(' + wf.匹配条件脚本 + ')') : noop;
        const result = onMatch({ UID, record });
        if (result !== false) {
          wf_matchs.push(wf);
        }
      });
      if (wf_matchs.length === 0) throw Error("未匹配到有效的流程定义");
      if (wf_matchs.length > 1) throw Error("匹配到多个流程定义: " + wf_matchs.map(wf => wf.名称).join(', '));
    } else {
      wf_matchs.push(wfs[0]);
    }
    const wf = wf_matchs[0];

    // 2. 遍历所有节点
    const { Rows: nodes } = A.job.CardR(UID, 'B.流程节点', null, [['流程定义', '=', wf.ID]]);
    wf.nodes = nodes.map(n => {
      n.prev = []; // 存放路径连接的所有前置节点
      n.next = []; // 存放路径连接的所有后置节点

      // 单独指向开始和结束节点
      if (n.类型 === 1) wf.start = n;
      if (n.类型 === 2) wf.end = n;

      // 反序列化脚本
      n.onArrive = n.流入脚本 ? eval('(' + n.流入脚本 + ')') : noop;
      n.onLeave = n.流出脚本 ? eval('(' + n.流出脚本 + ')') : noop;
      n.onGetUsers = n.待办用户脚本 ? eval('(' + n.待办用户脚本 + ')') : noop;
      n.onGetDesc = n.待办描述脚本 || wf.待办描述脚本 ? eval('(' + (n.待办描述脚本 || wf.待办描述脚本) + ')') : noop;
      return n;
    });
    wf.node = id => wf.nodes.find(n => n.ID === id);

    // 3. 遍历所有路径
    const { Rows: edges } = A.job.CardR(UID, 'B.流程路径', null, [['流程定义', '=', wf.ID]]);
    edges.forEach(edge => {
      // 把入口节点添加到出口节点的前置集合中
      wf.node(edge.出口节点).prev.push(wf.node(edge.入口节点));
      // 把出口节点添加到入口节点的后置集合中
      wf.node(edge.入口节点).next.push({
        onValidate: edge.通行条件脚本 ? eval('(' + edge.通行条件脚本 + ')') : noop,
        node: wf.node(edge.出口节点),
      });
    });

    // 返回结果
    return wf;
  };
})()